#include "string.h"
#include "stdlib.h"
#include "i2c.h"
#include "rtthread.h"
#include "INA226\INA226.h"

uint8_t INA226_SetConfig(uint16_t ConfigWord);
uint8_t INA226_SetCalibrationReg(uint16_t ConfigWord);

#define INA226_COM_PORT                hi2c2 /*通讯使用的IIC接口*/

#define INA226_ADDRESS                 0x80 /*INA226的地址*/
#define INA226_I2C_TIMEOUT             10   /*IIC通讯超时*/

#define INA226_CALIB_VAL               1024
#define INA226_CURRENTLSB              0.5F                         // mA/bit
#define INA226_CURRENTLSB_INV          1 / INA226_CURRENTLSB        // bit/mA
#define INA226_POWERLSB_INV            1 / (INA226_CURRENTLSB * 25) // bit/mW

#define INA226_MODE_POWER_DOWN         (0 << 0) // Power-Down
#define INA226_MODE_TRIG_SHUNT_VOLTAGE (1 << 0) // Shunt Voltage, Triggered
#define INA226_MODE_TRIG_BUS_VOLTAGE   (2 << 0) // Bus Voltage, Triggered
#define INA226_MODE_TRIG_SHUNT_AND_BUS (3 << 0) // Shunt and Bus, Triggered
#define INA226_MODE_POWER_DOWN2        (4 << 0) // Power-Down
#define INA226_MODE_CONT_SHUNT_VOLTAGE (5 << 0) // Shunt Voltage, Continuous
#define INA226_MODE_CONT_BUS_VOLTAGE   (6 << 0) // Bus Voltage, Continuous
#define INA226_MODE_CONT_SHUNT_AND_BUS (7 << 0) // Shunt and Bus, Continuous

// Shunt Voltage Conversion Time
#define INA226_VSH_140uS  (0 << 3)
#define INA226_VSH_204uS  (1 << 3)
#define INA226_VSH_332uS  (2 << 3)
#define INA226_VSH_588uS  (3 << 3)
#define INA226_VSH_1100uS (4 << 3)
#define INA226_VSH_2116uS (5 << 3)
#define INA226_VSH_4156uS (6 << 3)
#define INA226_VSH_8244uS (7 << 3)

// Bus Voltage Conversion Time (VBUS CT Bit Settings[6-8])
#define INA226_VBUS_140uS  (0 << 6)
#define INA226_VBUS_204uS  (1 << 6)
#define INA226_VBUS_332uS  (2 << 6)
#define INA226_VBUS_588uS  (3 << 6)
#define INA226_VBUS_1100uS (4 << 6)
#define INA226_VBUS_2116uS (5 << 6)
#define INA226_VBUS_4156uS (6 << 6)
#define INA226_VBUS_8244uS (7 << 6)

// Averaging Mode (AVG Bit Settings[9-11])
#define INA226_AVG_1    (0 << 9)
#define INA226_AVG_4    (1 << 9)
#define INA226_AVG_16   (2 << 9)
#define INA226_AVG_64   (3 << 9)
#define INA226_AVG_128  (4 << 9)
#define INA226_AVG_256  (5 << 9)
#define INA226_AVG_512  (6 << 9)
#define INA226_AVG_1024 (7 << 9)

// Reset Bit (RST bit [15])
#define INA226_RESET_ACTIVE   (1 << 15)
#define INA226_RESET_INACTIVE (0 << 15)

// Mask/Enable Register
#define INA226_MER_SOL          (1 << 15) // Shunt Voltage Over-Voltage
#define INA226_MER_SUL          (1 << 14) // Shunt Voltage Under-Voltage
#define INA226_MER_BOL          (1 << 13) // Bus Voltagee Over-Voltage
#define INA226_MER_BUL          (1 << 12) // Bus Voltage Under-Voltage
#define INA226_MER_POL          (1 << 11) // Power Over-Limit
#define INA226_MER_CNVR         (1 << 10) // Conversion Ready
#define INA226_MER_AFF          (1 << 4)  // Alert Function Flag
#define INA226_MER_CVRF         (1 << 3)  // Conversion Ready Flag
#define INA226_MER_OVF          (1 << 2)  // Math Overflow Flag
#define INA226_MER_APOL         (1 << 1)  // Alert Polarity Bit
#define INA226_MER_LEN          (1 << 0)  // Alert Latch Enable

#define INA226_MANUF_ID_DEFAULT 0x5449
#define INA226_DIE_ID_DEFAULT   0x2260

#define INA226_AVG              INA226_AVG_16
#define INA226_VBUS             INA226_VBUS_588uS
#define INA226_VSH              INA226_VSH_588uS
#define INA226_MODE             INA226_MODE_CONT_SHUNT_AND_BUS

// 全局变量，并进行初始化
INA226_Data sensor_data = {
    .shuntV         = 0,
    .voltage        = 0,
    .current        = 0,
    .power          = 0,
    .energy         = 0,
    .max_voltage    = 0,
    .max_current    = 0,
    .max_power      = 0,
    .raw_shuntV     = 0,
    .raw_voltage    = 0,   // 电压原始值初始化为 0
    .raw_current    = 0,   // 电流原始值初始化为 0
    .raw_power      = 0,   // 功率原始值初始化为 0
    .voltage_buffer = {0}, // 电压缓冲区初始化为 0
    .current_buffer = {0}, // 电流缓冲区初始化为 0
};

static float R_shunt = 10.0f; // mR

void INA226_init(void)
{
    uint32_t ConfigBit = 0x4000 + INA226_AVG + INA226_VBUS + INA226_VSH + INA226_MODE;
    INA226_SetConfig(ConfigBit);

    /*
     * 分流电阻最大电压 = 32768 * 0.0000025V = 0.08192V
     * 设置分流电压转电流转换参数:电阻0.01R，分辨率0.2mA
     * 公式1
     * Current_LSB = 预期最大电流 / 2^15
     * Current_LSB = 5 / 32768 = 0.000152A ,选0.2ma
     * 公式2
     * CAL = 0.00512/(Current_LSB*R)
     * CAL = 0.00512/(0.0002*0.01)=2560 = 0x0a00
     */
    INA226_SetCalibrationReg(0x6400);
    sensor_data.energy = 0;
}

void INA226_SensorUpdate(void)
{
    uint16_t raw_temp[BUFFER_SIZE] = {0};

    sensor_data.raw_shuntV  = INA226_GetShuntV();
    sensor_data.raw_voltage = INA226_GetBusVReg();
    sensor_data.raw_current = INA226_GetCurrentReg();
    sensor_data.raw_power   = INA226_GetPowerReg();
    // if ((sensor_data.raw_shuntV > -80) && (sensor_data.raw_shuntV < 0)) sensor_data.raw_shuntV = 0;
    // if ((sensor_data.raw_current > -80) && (sensor_data.raw_current < 0)) sensor_data.raw_current = 0;
    // if (sensor_data.raw_power < 40) sensor_data.raw_power = 0;

    sensor_data.shuntV  = sensor_data.raw_shuntV * 2.5f;
    sensor_data.voltage = sensor_data.raw_voltage * 1.25f;
    sensor_data.current = sensor_data.raw_current * 0.2;
    sensor_data.power   = sensor_data.voltage * abs(sensor_data.current) / 1000;
    sensor_data.energy += sensor_data.current / 30 / 3.6; // 采样率10Hz

    if (sensor_data.voltage > sensor_data.max_voltage) sensor_data.max_voltage = sensor_data.voltage;
    if (sensor_data.current > sensor_data.max_voltage) sensor_data.max_current = sensor_data.current;
    if (sensor_data.power > sensor_data.max_voltage) sensor_data.max_power = sensor_data.power;

    memcpy(raw_temp, sensor_data.voltage_buffer + 1, 9 * sizeof(uint16_t));
    raw_temp[9] = sensor_data.voltage;
    memcpy(sensor_data.voltage_buffer, raw_temp, 10 * sizeof(uint16_t));
    memcpy(raw_temp, sensor_data.current_buffer + 1, 9 * sizeof(uint16_t));
    raw_temp[9] = sensor_data.current;
    memcpy(sensor_data.current_buffer, raw_temp, 10 * sizeof(uint16_t));
}
/*
**************************************************
* 说明：读取BUS电压，并转换为浮点数据
**************************************************
*/
// float INA226_GetBusV(void)
// {
//     uint16_t regData;
//     float fVoltage;
//     regData  = INA226_GetBusVReg();
//     fVoltage = regData * 1.25f; /*电压的LSB = 1.25mV*/
//     return fVoltage;
// }
/*
**************************************************
* 说明：读取电流，并转换为浮点数据
**************************************************
*/
// float INA226_GetCurrent()
// {
//     uint16_t regData;
//     float fCurrent;
//     regData = INA226_GetCurrentReg();
//     if (regData >= 0x8000) regData = 0;
//     fCurrent = regData * 4; /*电流的LSB = 0.2mA，由用户配置*/
//     return fCurrent;
// }
/*
**************************************************
* 说明：读取功率，并转换为浮点数据
**************************************************
*/
// float INA226_GetPower()
// {
//     uint16_t regData;
//     float fPower;
//     regData = INA226_GetPowerReg();
//     fPower  = regData * 10; /*功率的LSB = 电流的LSB*25*/
//     return fPower;
// }

uint8_t INA226_SetConfig(uint16_t ConfigWord)
{
    uint8_t SentTable[3];
    SentTable[0] = INA226_CONFIG;
    SentTable[1] = (ConfigWord & 0xFF00) >> 8;
    SentTable[2] = (ConfigWord & 0x00FF);
    return HAL_I2C_Master_Transmit(&INA226_COM_PORT, INA226_ADDRESS, SentTable, 3, INA226_I2C_TIMEOUT);
}

// uint16_t INA226_GetConfig()
// {
//     uint8_t SentTable[1] = {INA226_CONFIG};
//     uint8_t ReceivedTable[2];
//     HAL_I2C_Master_Transmit(&INA226_COM_PORT,INA226_ADDRESS, SentTable, 1, INA226_I2C_TIMEOUT);
//     if (HAL_I2C_Master_Receive(&INA226_COM_PORT,INA226_ADDRESS, ReceivedTable, 2, INA226_I2C_TIMEOUT) != HAL_OK) return 0xFF;
//     else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
// }

// uint16_t INA226_GetShuntV()
// {
//     uint8_t SentTable[1] = {INA226_SHUNTV};
//     uint8_t ReceivedTable[2];
//     HAL_I2C_Master_Transmit(&INA226_COM_PORT,INA226_ADDRESS, SentTable, 1, INA226_I2C_TIMEOUT);
//     if (HAL_I2C_Master_Receive(&INA226_COM_PORT,INA226_ADDRESS, ReceivedTable, 2, INA226_I2C_TIMEOUT) != HAL_OK) return 0xFF;
//     else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
// }

uint8_t INA226_SetCalibrationReg(uint16_t ConfigWord)
{
    uint8_t SentTable[3];
    SentTable[0] = INA226_CALIB;
    SentTable[1] = (ConfigWord & 0xFF00) >> 8;
    SentTable[2] = (ConfigWord & 0x00FF);
    return HAL_I2C_Master_Transmit(&INA226_COM_PORT, INA226_ADDRESS, SentTable, 3, INA226_I2C_TIMEOUT);
}

// uint16_t INA226_GetCalibrationReg()
// {
//     uint8_t SentTable[1] = {INA226_CALIB};
//     uint8_t ReceivedTable[2];
//     HAL_I2C_Master_Transmit(&INA226_COM_PORT,INA226_ADDRESS, SentTable, 1, INA226_I2C_TIMEOUT);
//     if (HAL_I2C_Master_Receive(&INA226_COM_PORT,INA226_ADDRESS, ReceivedTable, 2, INA226_I2C_TIMEOUT) != HAL_OK) return 0xFF;
//     else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
// }
uint16_t INA226_GetReg(uint8_t RegAddr)
{
    uint8_t receivedData[2];
    HAL_StatusTypeDef status;

    // 读取两个字节数据
    status = HAL_I2C_Mem_Read(&INA226_COM_PORT, INA226_ADDRESS,
                              RegAddr, I2C_MEMADD_SIZE_8BIT,
                              receivedData, 2, INA226_I2C_TIMEOUT);

    if (status != HAL_OK) {
        return 0xFF; // 读取失败
    }

    // 合并两个字节并返回
    return ((uint16_t)receivedData[0] << 8 | receivedData[1]);
}

// uint16_t INA226_GetManufID()
// {
//     uint8_t SentTable[1] = {INA226_MANUF_ID};
//     uint8_t ReceivedTable[2];

//     HAL_I2C_Master_Transmit(&INA226_COM_PORT,INA226_ADDRESS, SentTable, 1, INA226_I2C_TIMEOUT);
//     if (HAL_I2C_Master_Receive(&INA226_COM_PORT,INA226_ADDRESS, ReceivedTable, 2, INA226_I2C_TIMEOUT) != HAL_OK) return 0xFF;
//     else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
// }

// uint16_t INA226_GetDieID()
// {
//     uint8_t SentTable[1] = {INA226_DIE_ID};
//     uint8_t ReceivedTable[2];
//     HAL_I2C_Master_Transmit(&INA226_COM_PORT,INA226_ADDRESS, SentTable, 1, INA226_I2C_TIMEOUT);
//     if (HAL_I2C_Master_Receive(&INA226_COM_PORT,INA226_ADDRESS, ReceivedTable, 2, INA226_I2C_TIMEOUT) != HAL_OK) return 0xFF;
//     else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
// }

// uint8_t INA226_SetMaskEnable(uint16_t ConfigWord)
// {
//     uint8_t SentTable[3];
//     SentTable[0] = INA226_MASK;
//     SentTable[1] = (ConfigWord & 0xFF00) >> 8;
//     SentTable[2] = (ConfigWord & 0x00FF);
//     return HAL_I2C_Master_Transmit(&INA226_COM_PORT, INA226_ADDRESS, SentTable, 3, INA226_I2C_TIMEOUT);
// }

// uint16_t INA226_GetMaskEnable()
// {
//     uint8_t SentTable[1] = {INA226_MASK};
//     uint8_t ReceivedTable[2];
//     HAL_I2C_Master_Transmit(&INA226_COM_PORT,INA226_ADDRESS, SentTable, 1, INA226_I2C_TIMEOUT);
//     if (HAL_I2C_Master_Receive(&INA226_COM_PORT,INA226_ADDRESS, ReceivedTable, 2, INA226_I2C_TIMEOUT) != HAL_OK) return 0xFF;
//     else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
// }

// uint8_t INA226_SetAlertLimit(uint16_t ConfigWord)
// {
//     uint8_t SentTable[3];
//     SentTable[0] = INA226_ALERTL;
//     SentTable[1] = (ConfigWord & 0xFF00) >> 8;
//     SentTable[2] = (ConfigWord & 0x00FF);
//     return HAL_I2C_Master_Transmit(&INA226_COM_PORT, INA226_ADDRESS, SentTable, 3, INA226_I2C_TIMEOUT);
// }

// uint16_t INA226_GetAlertLimit()
// {
//     uint8_t SentTable[1] = {INA226_ALERTL};
//     uint8_t ReceivedTable[2];
//     HAL_I2C_Master_Transmit(&INA226_COM_PORT,INA226_ADDRESS, SentTable, 1, INA226_I2C_TIMEOUT);
//     if (HAL_I2C_Master_Receive(&INA226_COM_PORT,INA226_ADDRESS, ReceivedTable, 2, INA226_I2C_TIMEOUT) != HAL_OK) return 0xFF;
//     else return ((uint16_t)ReceivedTable[0]<<8 | ReceivedTable[1]);
// }
